"""
第1章：路由与参数 - 实战练习代码
配合 chapter01_routing.md 讲义使用

运行方式：
cd /Users/baimu/PycharmProjects/fastApiProject3
uvicorn stage1_basics.chapter01_routing_practice:app --reload --port 8002

访问：
- Swagger UI: http://127.0.0.1:8002/docs
- 根路径: http://127.0.0.1:8002/
"""

from fastapi import FastAPI, Path, Query
from typing import Optional
from enum import Enum

# ========== 应用初始化 ==========

app = FastAPI(
    title="第1章：路由与参数练习",
    description="FastAPI 路由与参数的完整示例",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc",
)

# ========== 1. 基础路由 ==========


@app.get("/", tags=["根路径"])
async def root():
    """
    根路径
    
    返回欢迎信息和可用端点列表
    """
    return {
        "message": "欢迎来到第1章：路由与参数练习！",
        "endpoints": {
            "根路径": "/",
            "基础路由": "/demo/basic",
            "路径参数": "/users/{user_id}",
            "查询参数": "/items",
            "混合参数": "/users/{user_id}/items",
        },
        "docs": "/docs",
    }


# ========== 2. HTTP 方法示例 ==========


@app.get("/demo/basic", tags=["HTTP方法示例"])
async def basic_get():
    """GET 方法示例"""
    return {"method": "GET", "message": "获取资源"}


@app.post("/demo/basic", tags=["HTTP方法示例"])
async def basic_post():
    """POST 方法示例"""
    return {"method": "POST", "message": "创建资源"}


@app.put("/demo/basic/{resource_id}", tags=["HTTP方法示例"])
async def basic_put(resource_id: int):
    """PUT 方法示例"""
    return {"method": "PUT", "message": f"完整更新资源 {resource_id}"}


@app.patch("/demo/basic/{resource_id}", tags=["HTTP方法示例"])
async def basic_patch(resource_id: int):
    """PATCH 方法示例"""
    return {"method": "PATCH", "message": f"部分更新资源 {resource_id}"}


@app.delete("/demo/basic/{resource_id}", tags=["HTTP方法示例"])
async def basic_delete(resource_id: int):
    """DELETE 方法示例"""
    return {"method": "DELETE", "message": f"删除资源 {resource_id}"}


# ========== 3. 路径参数基础 ==========


@app.get("/users/{user_id}", tags=["路径参数"])
async def get_user_basic(user_id: int):
    """
    基础路径参数
    
    - **user_id**: 用户ID（整数）
    """
    return {"user_id": user_id, "type": type(user_id).__name__}


@app.get("/items/{item_id}/details", tags=["路径参数"])
async def get_item_details(item_id: str):
    """
    字符串路径参数
    
    - **item_id**: 商品ID（字符串）
    """
    return {"item_id": item_id, "type": type(item_id).__name__}


@app.get("/files/{file_path:path}", tags=["路径参数"])
async def get_file(file_path: str):
    """
    路径类型参数（可以包含斜杠）
    
    示例: /files/home/user/document.pdf
    
    - **file_path**: 文件路径
    """
    return {"file_path": file_path}


# ========== 4. 枚举路径参数 ==========


class ModelName(str, Enum):
    """机器学习模型名称枚举"""

    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


@app.get("/models/{model_name}", tags=["路径参数"])
async def get_model(model_name: ModelName):
    """
    枚举路径参数
    
    只能是以下值之一：
    - alexnet
    - resnet
    - lenet
    """
    return {
        "model_name": model_name,
        "model_value": model_name.value,
        "message": f"您选择的模型是: {model_name.value}",
    }


# ========== 5. Path() 参数验证 ==========


@app.get("/validated/items/{item_id}", tags=["参数验证"])
async def get_validated_item(
    item_id: int = Path(
        ..., title="商品ID", description="商品的唯一标识符", ge=1, le=1000, example=42
    )
):
    """
    使用 Path() 进行参数验证
    
    - **item_id**: 必须是1-1000之间的整数
    """
    return {"item_id": item_id, "validation": "通过"}


@app.get("/validated/users/{username}", tags=["参数验证"])
async def get_validated_user(
    username: str = Path(
        ...,
        min_length=3,
        max_length=20,
        pattern="^[a-zA-Z0-9_]+$",
        description="用户名，3-20个字符，只能包含字母、数字和下划线",
        example="john_doe",
    )
):
    """
    字符串路径参数验证
    
    - **username**: 3-20个字符，只能包含字母、数字和下划线
    """
    return {"username": username, "validation": "通过"}


# ========== 6. 查询参数基础 ==========


@app.get("/items", tags=["查询参数"])
async def list_items(skip: int = 0, limit: int = 10):
    """
    基础查询参数（带默认值）
    
    - **skip**: 跳过的记录数（默认0）
    - **limit**: 返回的记录数（默认10）
    
    示例: /items?skip=0&limit=10
    """
    return {"skip": skip, "limit": limit, "items": list(range(skip, skip + limit))}


@app.get("/search", tags=["查询参数"])
async def search(q: str):
    """
    必需查询参数（无默认值）
    
    - **q**: 搜索关键词（必需）
    
    示例: /search?q=python
    """
    return {"q": q, "message": f"搜索关键词: {q}"}


@app.get("/products", tags=["查询参数"])
async def list_products(q: Optional[str] = None):
    """
    可选查询参数（可为 None）
    
    - **q**: 搜索关键词（可选）
    
    示例:
    - /products → q = None
    - /products?q=laptop → q = "laptop"
    """
    if q:
        return {"q": q, "message": f"搜索: {q}"}
    return {"message": "返回所有产品"}


# ========== 7. Query() 参数验证 ==========


@app.get("/validated/search", tags=["参数验证"])
async def validated_search(
    q: str = Query(
        ...,
        min_length=1,
        max_length=100,
        description="搜索关键词",
        example="FastAPI",
    )
):
    """
    使用 Query() 进行参数验证
    
    - **q**: 搜索关键词，1-100个字符（必需）
    """
    return {"q": q, "length": len(q)}


@app.get("/validated/users", tags=["参数验证"])
async def validated_list_users(
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(10, ge=1, le=100, description="返回的记录数，最多100"),
    sort: str = Query(
        "id", pattern="^(id|name|created_at)$", description="排序字段: id/name/created_at"
    ),
):
    """
    多个查询参数验证
    
    - **skip**: 大于等于0
    - **limit**: 1-100之间
    - **sort**: 只能是 id, name, created_at 之一
    """
    return {"skip": skip, "limit": limit, "sort": sort}


# ========== 8. 列表查询参数 ==========


@app.get("/items/filter", tags=["查询参数"])
async def filter_items(tags: list[str] = Query([], description="标签列表")):
    """
    列表查询参数
    
    - **tags**: 标签列表
    
    示例: /items/filter?tags=python&tags=fastapi&tags=api
    """
    return {"tags": tags, "count": len(tags)}


# ========== 9. 混合使用路径参数和查询参数 ==========


@app.get("/users/{user_id}/items", tags=["混合参数"])
async def get_user_items(
    # 路径参数
    user_id: int = Path(..., ge=1, description="用户ID"),
    # 查询参数
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(10, ge=1, le=100, description="返回的记录数"),
    q: Optional[str] = Query(None, min_length=3, description="搜索关键词"),
):
    """
    混合使用路径参数和查询参数
    
    路径参数:
    - **user_id**: 用户ID（必需）
    
    查询参数:
    - **skip**: 跳过的记录数
    - **limit**: 返回的记录数
    - **q**: 搜索关键词（可选）
    
    示例: /users/123/items?skip=0&limit=10&q=python
    """
    result = {
        "user_id": user_id,
        "skip": skip,
        "limit": limit,
        "items": [f"item_{i}" for i in range(skip, skip + limit)],
    }

    if q:
        result["search"] = q

    return result


@app.get("/categories/{category}/products/{product_id}", tags=["混合参数"])
async def get_category_product(
    category: str = Path(..., min_length=2, description="分类名称"),
    product_id: int = Path(..., ge=1, description="产品ID"),
    include_details: bool = Query(False, description="是否包含详细信息"),
    include_reviews: bool = Query(False, description="是否包含评论"),
):
    """
    多个路径参数 + 多个查询参数
    
    示例: /categories/electronics/products/42?include_details=true&include_reviews=true
    """
    result = {"category": category, "product_id": product_id}

    if include_details:
        result["details"] = {"brand": "示例品牌", "model": "XYZ-123"}

    if include_reviews:
        result["reviews"] = [{"rating": 5, "comment": "很好"}]

    return result


# ========== 10. 实战示例：商品搜索 API ==========


class ProductCategory(str, Enum):
    """商品分类"""

    electronics = "电子产品"
    books = "图书"
    clothing = "服装"
    food = "食品"


@app.get("/api/products/search", tags=["实战示例"])
async def search_products(
    q: Optional[str] = Query(
        None, min_length=1, max_length=100, description="搜索关键词"
    ),
    category: Optional[ProductCategory] = Query(None, description="商品分类"),
    min_price: float = Query(0, ge=0, description="最低价格"),
    max_price: float = Query(100000, ge=0, description="最高价格"),
    in_stock: Optional[bool] = Query(None, description="是否有货"),
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(20, ge=1, le=100, description="返回的记录数"),
    sort: str = Query(
        "relevance",
        pattern="^(relevance|price|date|rating)$",
        description="排序方式: relevance/price/date/rating",
    ),
):
    """
    商品搜索 API（综合示例）
    
    支持的功能：
    - 关键词搜索
    - 分类筛选
    - 价格区间筛选
    - 库存筛选
    - 分页
    - 排序
    
    示例:
    /api/products/search?q=笔记本&category=electronics&min_price=3000&max_price=8000&in_stock=true&skip=0&limit=20&sort=price
    """
    filters = {
        "search_query": q,
        "category": category.value if category else None,
        "price_range": {"min": min_price, "max": max_price},
    }

    if in_stock is not None:
        filters["in_stock"] = in_stock

    return {
        "filters": filters,
        "pagination": {"skip": skip, "limit": limit},
        "sort": sort,
        "total": 100,  # 模拟总数
        "products": [
            {
                "id": i,
                "name": f"商品 {i}",
                "price": min_price + (i * 100),
                "category": category.value if category else "未分类",
                "in_stock": True,
            }
            for i in range(skip + 1, min(skip + limit + 1, 21))
        ],
    }


# ========== 11. 实战示例：用户管理 API ==========


@app.get("/api/users/{user_id}", tags=["实战示例"])
async def get_user_detail(
    user_id: int = Path(..., ge=1, description="用户ID"),
    include_posts: bool = Query(False, description="是否包含用户的文章"),
    include_comments: bool = Query(False, description="是否包含用户的评论"),
    include_profile: bool = Query(True, description="是否包含用户资料"),
):
    """
    获取用户详细信息
    
    可选择包含：
    - 用户文章
    - 用户评论
    - 用户资料（默认包含）
    
    示例: /api/users/123?include_posts=true&include_comments=true
    """
    result = {
        "user_id": user_id,
        "username": f"user_{user_id}",
        "email": f"user{user_id}@example.com",
    }

    if include_profile:
        result["profile"] = {
            "bio": "这是用户简介",
            "avatar": "https://example.com/avatar.jpg",
            "joined_date": "2024-01-01",
        }

    if include_posts:
        result["posts"] = [
            {"id": 1, "title": "我的第一篇文章"},
            {"id": 2, "title": "FastAPI 教程"},
        ]

    if include_comments:
        result["comments"] = [
            {"id": 1, "content": "很有帮助！"},
            {"id": 2, "content": "感谢分享"},
        ]

    return result


@app.get("/api/users", tags=["实战示例"])
async def list_users_advanced(
    role: Optional[str] = Query(
        None, pattern="^(admin|user|guest)$", description="角色筛选: admin/user/guest"
    ),
    active: Optional[bool] = Query(None, description="是否激活"),
    registered_after: Optional[str] = Query(
        None, pattern=r"^\d{4}-\d{2}-\d{2}$", description="注册日期之后（YYYY-MM-DD）"
    ),
    search: Optional[str] = Query(None, min_length=2, description="搜索用户名或邮箱"),
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(20, ge=1, le=100, description="返回的记录数"),
    sort: str = Query(
        "created_at", pattern="^(id|username|created_at)$", description="排序字段"
    ),
    order: str = Query("desc", pattern="^(asc|desc)$", description="排序顺序"),
):
    """
    获取用户列表（高级筛选）
    
    支持的筛选条件：
    - **role**: 角色筛选
    - **active**: 激活状态
    - **registered_after**: 注册日期筛选
    - **search**: 搜索关键词
    - **sort**: 排序字段
    - **order**: 排序顺序
    
    示例:
    /api/users?role=admin&active=true&registered_after=2024-01-01&search=john&skip=0&limit=20&sort=username&order=asc
    """
    filters = {}
    if role:
        filters["role"] = role
    if active is not None:
        filters["active"] = active
    if registered_after:
        filters["registered_after"] = registered_after
    if search:
        filters["search"] = search

    return {
        "filters": filters,
        "pagination": {"skip": skip, "limit": limit},
        "sort": {"field": sort, "order": order},
        "total": 50,  # 模拟总数
        "users": [
            {
                "id": i,
                "username": f"user_{i}",
                "email": f"user{i}@example.com",
                "role": role or "user",
                "active": active if active is not None else True,
                "created_at": "2024-01-01T00:00:00",
            }
            for i in range(skip + 1, min(skip + limit + 1, 21))
        ],
    }


# ========== 12. 路由顺序示例 ==========


@app.get("/demo/order/me", tags=["路由顺序"])
async def get_me():
    """
    特定路由（必须在动态路由之前）
    
    访问: /demo/order/me
    """
    return {"user": "current_user", "note": "这是特定路由"}


@app.get("/demo/order/{user_id}", tags=["路由顺序"])
async def get_user_by_id(user_id: int):
    """
    动态路由（在特定路由之后）
    
    访问: /demo/order/123
    """
    return {"user_id": user_id, "note": "这是动态路由"}


# ========== 启动信息 ==========

if __name__ == "__main__":
    print("=" * 70)
    print("📚 第1章：路由与参数 - 实战练习")
    print("=" * 70)
    print("\n启动命令:")
    print("uvicorn stage1_basics.chapter01_routing_practice:app --reload --port 8002\n")
    print("访问地址:")
    print("- Swagger UI: http://127.0.0.1:8002/docs")
    print("- ReDoc: http://127.0.0.1:8002/redoc")
    print("- 根路径: http://127.0.0.1:8002/")
    print("\n建议：")
    print("1. 先访问 Swagger UI 查看所有端点")
    print("2. 逐个测试不同的参数组合")
    print("3. 观察参数验证的效果")
    print("4. 尝试传入错误的参数，看看错误信息")
    print("\n" + "=" * 70)

